package com.stone.serviceimpl;


import com.stone.dao.IPhotoDao;
import java.io.File;
import java.io.StringReader;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.analysis.TokenStream;
import org.apache.lucene.analysis.standard.StandardAnalyzer;
import org.apache.lucene.document.Document;
import org.apache.lucene.document.Field;
import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.queryParser.MultiFieldQueryParser;
import org.apache.lucene.search.BooleanClause;
import org.apache.lucene.search.Filter;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.ScoreDoc;
import org.apache.lucene.search.TopDocs;
import org.apache.lucene.search.highlight.Highlighter;
import org.apache.lucene.search.highlight.QueryScorer;
import org.apache.lucene.search.highlight.SimpleFragmenter;
import org.apache.lucene.search.highlight.SimpleHTMLFormatter;
import org.apache.lucene.store.Directory;
import org.apache.lucene.store.FSDirectory;

import com.stone.dao.IStoneDao;
import com.stone.model.Photo;
import com.stone.model.Stone;
import com.stone.service.IStoneService;
import com.stone.utils.Page;

public class StoneService implements IStoneService {
	private IStoneDao stoneDao; 

	private IPhotoDao photoDao;
	
	private final String INDEXPATH = "\\stone_index";
	private Analyzer analyzer = new StandardAnalyzer();
	/*getter setter*/
	public IStoneDao getStoneDao() {
		return stoneDao;
	}
	public void setStoneDao(IStoneDao stoneDao) {
		this.stoneDao = stoneDao;
	}
	/*service method*/
	public Page getHighSearchStone(String path,String query,int pageno, int pagesize) {
		try{
		List<Stone> qlist = new ArrayList<Stone>();
//		String fieldName = "title";
		//System.out.println(path+INDEXPATH);
		IndexSearcher indexSearcher = new IndexSearcher(path+INDEXPATH);
		//QueryParser parser = new QueryParser(fieldName, analyzer); //单 key 搜索
		//Query queryOBJ = parser.parse(query);
	//	System.out.println(">>> 2.开始读取索引... ... 通过关键字：【 "+ query +" 】");
		long begin = new Date().getTime();
		//下面的是进行title,content 两个范围内进行收索.
		BooleanClause.Occur[] clauses = { BooleanClause.Occur.SHOULD,BooleanClause.Occur.SHOULD,BooleanClause.Occur.SHOULD,BooleanClause.Occur.SHOULD,BooleanClause.Occur.SHOULD,BooleanClause.Occur.SHOULD,BooleanClause.Occur.SHOULD,BooleanClause.Occur.SHOULD,BooleanClause.Occur.SHOULD };
		Query queryOBJ = MultiFieldQueryParser.parse(query, new String[]{"chinesename","englishname","sourceland","color","venation","material","purpose","shortdescription","successfulcase"}, clauses, new StandardAnalyzer());//parser.parse(query);
		Filter filter = null;
		//################# 搜索相似度最高的记录 ###################
		TopDocs topDocs = indexSearcher.search(queryOBJ, filter,100);
		int totalHits = topDocs.totalHits;
		//TopDocs topDocs = indexSearcher.search(queryOBJ , 10000);
		//System.out.println("*** 共匹配：" + totalHits + "个 ***");
		Page page = new Page(totalHits,pagesize);
		Stone stone = null;
		int startResult = (pageno-1)*pagesize;
		int endResult = (startResult+pagesize)<totalHits?(startResult+pagesize):totalHits;
		ScoreDoc scoreDoc[] = topDocs.scoreDocs;
		//输出结果
		page.setTotalRows(0);
		for(int i=startResult; i<endResult; i++){
//		for (ScoreDoc scoreDoc : topDocs.scoreDocs){
				Document targetDoc = indexSearcher.doc(scoreDoc[i].doc);
				stone = new Stone();
				//设置高亮显示格式
				SimpleHTMLFormatter simpleHTMLFormatter = new SimpleHTMLFormatter("<font class='red'>", "</font>"); 
				/* 语法高亮显示设置 */
				Highlighter highlighter = new Highlighter(simpleHTMLFormatter,new QueryScorer(queryOBJ)); 
				highlighter.setTextFragmenter(new SimpleFragmenter(100)); 
				
				// 设置高亮 设置 title,content 字段
				String name = targetDoc.get("chinesename");
				String desc = targetDoc.get("shortdescription");
				String englishName = targetDoc.get("englishname");
				String sourceLand = targetDoc.get("sourceland");
				String color = targetDoc.get("color");
				String material = targetDoc.get("material");
				String venation = targetDoc.get("venation");
				String purpose = targetDoc.get("purpose");
				String successfulCase = targetDoc.get("successfulcase");
				TokenStream nameTokenStream = analyzer.tokenStream("chinesename",new StringReader(name));
				TokenStream colorTokenStream = analyzer.tokenStream("color",new StringReader(color));
				TokenStream enameTokenStream = analyzer.tokenStream("englishname",new StringReader(englishName));
				TokenStream landTokenStream = analyzer.tokenStream("sourceland",new StringReader(sourceLand));
				TokenStream materialTokenStream = analyzer.tokenStream("material",new StringReader(material));
				TokenStream venationTokenStream = analyzer.tokenStream("venation",new StringReader(venation));
				TokenStream purposeTokenStream = analyzer.tokenStream("purpose",new StringReader(purpose));
				TokenStream descTokenStream = analyzer.tokenStream("shortdescription",new StringReader(desc));
				TokenStream caseTokenStream = analyzer.tokenStream("successfulcase",new StringReader(successfulCase));
				String  highLightName = highlighter.getBestFragment(nameTokenStream, name);
				String  highLightEname = highlighter.getBestFragment(enameTokenStream, englishName);
				String  highLightLand = highlighter.getBestFragment(landTokenStream, sourceLand);
				String highLightColor = highlighter.getBestFragment(colorTokenStream, color);
				String  highLightMaterial = highlighter.getBestFragment(materialTokenStream, material);
				String highLightVenation = highlighter.getBestFragment(venationTokenStream, venation);
				String  highLightPurpose = highlighter.getBestFragment(purposeTokenStream, purpose);
				String highLightDesc = highlighter.getBestFragment(descTokenStream, desc);
				String highLightCase = highlighter.getBestFragment(caseTokenStream, successfulCase);
			     if(highLightName == null)
			    	 highLightName = name;
			     if(highLightDesc == null) 
			    	 highLightDesc = desc;
			     if(highLightColor == null)
			    	 highLightColor = color;
			     if(highLightMaterial == null) 
			    	 highLightMaterial = material;
			     if(highLightVenation == null)
			    	 highLightVenation = venation;
			     if(highLightPurpose == null) 
			    	 highLightPurpose = purpose;
			     if(highLightLand == null)
			    	 highLightLand = sourceLand;
			     if(highLightEname == null) 
			    	 highLightEname = englishName;
			     if(highLightCase == null) 
			    	 highLightCase = successfulCase;
			    stone.setId(Long.parseLong(targetDoc.get("s_id")));
			    stone.setChineseName(highLightName);
				stone.setShortDesc(highLightDesc);
				stone.setMaterial(highLightMaterial);
				stone.setColor(highLightColor);
				stone.setVenation(highLightVenation);
				stone.setPurpose(highLightPurpose);
				stone.setEnglishName(highLightEname);
				stone.setSourceland(highLightLand);
				stone.setSuccessfulCase(successfulCase);
				
				
				Stone tempStone = this.findStoneById(stone.getId());
				//为0的不显示
				if(tempStone.getDisplayFlag() != null)
				{
					if(!tempStone.getDisplayFlag().equals(new Integer(0)))
					{
						qlist.add(stone);
						page.setTotalRows(page.getTotalRows() + 1);
					}
					System.out.println(tempStone.getDisplayFlag());
				}
				else
				{
					System.out.println("null");
					qlist.add(stone);
				}
		}
		long end = new Date().getTime();
		//System.out.println(">>> 3.搜索完毕... ... 共花费：" + (end - begin) +"毫秒...");
		indexSearcher.close();
		page.setList(qlist);
		page.setCurrentPage(pageno);
		return page;
		}catch(Exception e){
			e.printStackTrace();
			return null;
		}
	}
	
	public boolean createIndex(String path)
	{
		if(this.isIndexExisted(path))
			return this.isIndexExisted(path);
		return createNewIndex(path);
	}
	public boolean createNewIndex(String path){
		List<Stone> list = stoneDao.findAll();
		try
		{
			Directory directory = FSDirectory.getDirectory(path+INDEXPATH);
			IndexWriter indexWriter = new IndexWriter(directory, analyzer ,true, IndexWriter.MaxFieldLength.LIMITED);
			long begin = new Date().getTime();
			for(Stone stone: list)
			{
				Document doc = new Document();
				String name = stone.getChineseName() == null ? "" : stone.getChineseName().trim();
				String ename = stone.getEnglishName() == null ? "" : stone.getEnglishName().trim();
				String land = stone.getSourceland() == null ? "" : stone.getSourceland().trim();
				String color = stone.getColor() == null ? "" : stone.getColor().trim();
				String venation = stone.getVenation() == null ? "" : stone.getVenation().trim();
				String material = stone.getMaterial() == null ? "" : stone.getMaterial().trim();
				String purpose = stone.getPurpose() == null ? "" : stone.getPurpose().trim();
				String desc = stone.getShortDesc() == null ? "" : stone.getShortDesc().trim();
				String successfulCase = stone.getSuccessfulCase()==null?"":stone.getSuccessfulCase().trim();
				doc.add(new Field("s_id", stone.getId().toString(), Field.Store.YES, Field.Index.ANALYZED, Field.TermVector.YES));
				doc.add(new Field("chinesename", name, Field.Store.YES, Field.Index.ANALYZED, Field.TermVector.YES));
				doc.add(new Field("englishname", ename, Field.Store.YES, Field.Index.ANALYZED, Field.TermVector.YES));
				doc.add(new Field("sourceland", land, Field.Store.YES, Field.Index.ANALYZED, Field.TermVector.YES));
				doc.add(new Field("color", color, Field.Store.YES, Field.Index.ANALYZED, Field.TermVector.YES));
				doc.add(new Field("venation", venation, Field.Store.YES, Field.Index.ANALYZED, Field.TermVector.YES));
				doc.add(new Field("material", material, Field.Store.YES, Field.Index.ANALYZED, Field.TermVector.YES));
				doc.add(new Field("purpose", purpose, Field.Store.YES, Field.Index.ANALYZED, Field.TermVector.YES));
				doc.add(new Field("shortdescription", desc, Field.Store.YES, Field.Index.ANALYZED, Field.TermVector.YES));
				doc.add(new Field("successfulcase",successfulCase,Field.Store.YES,Field.Index.ANALYZED,Field.TermVector.YES));
				indexWriter.addDocument(doc);
			}
			long end = new Date().getTime();
		//	System.out.println(">>> 1.存入索引完毕.. 共花费：" + (end - begin) +"毫秒...");
			indexWriter.optimize();
			indexWriter.close();
			return true;
		}catch(Exception e){
			e.printStackTrace();
			return false;
		}
	}
	/**
	 * check Index is Existed
	 * @return true or false
	 */
	private boolean isIndexExisted(String path)
	{
		try
		{
			File dir = new File(path+INDEXPATH);
			if(dir.listFiles()!=null&&dir.listFiles().length>0)
				return true;
			else
				return false;
			
		}catch(Exception e){
			e.printStackTrace();
			return false;
		}
	}
	
	public Stone addStone(Stone stone) {
		return stoneDao.save(stone);
	}
	public Page getNewUploadStones(int pageno, int pagesize) {
		//return stoneDao.findNewUploadStones4Page(pageno, pagesize);
		return stoneDao.findNewUploadDisplayStones4Page(pageno, pagesize);
	}
	public Page getVisitMostStones(int pageno, int pagesize) {
		return stoneDao.findVisitMostStones4Page(pageno, pagesize);
	}
	
	public Page getVisitMostDisplayStones(int pageno, int pagesize)
	{
		return stoneDao.findVisitMostDisplayStones4Page(pageno, pagesize);
	}
	
	public Page searchStoneByNew(Stone stone, int pageno, int pagesize) {
		return stoneDao.searchStoneByNew4Page(stone, pageno, pagesize);
	}
	public Page searchStoneByVisit(Stone stone, int pageno, int pagesize) {
		return stoneDao.searchStoneByVisit4Page(stone, pageno, pagesize);
	}
	public Page searchCompanyByStone(Stone stone, int pageno, int pagesize){
		return stoneDao.searchCompanyByStone(stone, pageno, pagesize);
	}
	public List<Stone> getLikelyStones(Stone stone, int size) {
		return stoneDao.findLikelyStones(stone, 1, size).getList();
	}
	public List<Stone> getAllStones() {
		return stoneDao.findAll();
	}
	public Stone getStoneById(Long id) {
		return stoneDao.findById(id);
	}
	public IPhotoDao getPhotoDao() {
		return photoDao;
	}
	public void setPhotoDao(IPhotoDao photoDao) {
		this.photoDao = photoDao;
	}
	public void updateStone(Stone stone) {
		// TODO Auto-generated method stub
		stoneDao.update(stone);
	}
	public Stone findStoneById(long stoneId) {
		// TODO Auto-generated method stub
		Stone s = stoneDao.findById(stoneId);
		return s;
	}
	public void addStonePhoto(Photo photo) {
		// TODO Auto-generated method stub
		photoDao.save(photo);
	}

	public List<Photo> findPhotosByStoneId(long stoneId) {
		// TODO Auto-generated method stub	
		return photoDao.findPhotoByStoneId(stoneId);
	}

	public Page getStoneList(int pageno, int pagesize) {
		// TODO Auto-generated method stub
		return this.stoneDao.getAllStone(pageno, pagesize);
	}
	public void deleteStone(Stone s) {
		// TODO Auto-generated method stub
		this.stoneDao.delete(s);
		
	}
	public Photo findPhotosById(long defaultPhotoId) {
		return photoDao.findById(defaultPhotoId);
	}
	public void updatePhoto(Photo p) {
		// TODO Auto-generated method stub
		this.photoDao.update(p);
	}
	public void deletePhoto(Photo p) {
		// TODO Auto-generated method stub
		this.photoDao.delete(p);
	}
	public int validateName(String chineseName) {
		// TODO Auto-generated method stub
		int flag = this.stoneDao.countByProperty("chineseName", chineseName);
		return flag;
	}
	public Page findStonePageByName(String stoneName, int pageno, int pagesize) {
		return stoneDao.getStonePageByName(stoneName, pageno, pagesize);
	}
	
	public Page findStonePageByColor(String category, int pageno, int pagesize)
	{
		return stoneDao.getStonePageByColor(category, pageno, pagesize);	
	}
	
	public Page findStonePageByPurpose(String category, int pageno,int pagesize)
	{
		return stoneDao.getStonePageByPurpose(category, pageno, pagesize);		
	}
}
